// ----------------------------------------------------------------------------
/**
 * @file    clientInformation.cpp
 *
 * @brief   .cpp file for clientInformation
 *
 *
 *
 * @author  Siddharth Sathyam <ssathy2@gmail.com>
 * @author  Alan Ruvalcaba <aruval3@gmail.com>
 * @author  Patrick LaMontagna <plamontagna@gmail.com
 *
 * @version 1.0
 *
 * @date    November 24th, 2011
 *
 */
// ----------------------------------------------------------------------------

#include "clientinformation.h"

// Constructors...
clientInformation::clientInformation(QString name, QTcpSocket* socket)
{
    if(name != NULL && socket != NULL)
    {
	userName = name;
	sock = socket;
    }
}

clientInformation::clientInformation(QString name, QStringList friendList)
{
    if(name != NULL)
    {
	userName = name;
	sock = new QTcpSocket();
    }
    stringListOfFriends = friendList;
}

// Getters
QTcpSocket* clientInformation::getSocket()
{
    if(sock != NULL)
    {
	return sock;
    }
}

QString clientInformation::getUserName()
{
    return userName;
}

bool clientInformation::addToFriendsList(clientInformation *buddy)
{
    bool addConfirmation = false;
    if(buddy != NULL)
    {
	if(!tableOfFriends.contains(buddy->getUserName()) && !stringListOfFriends.contains(buddy->getUserName()))
	{
	    tableOfFriends.insert(buddy->getUserName(), buddy);
	    stringListOfFriends.push_front(buddy->getUserName());
	    addConfirmation = true;
	}
	else
	{
	    addConfirmation = false;
	}
    }
    else
    {
	addConfirmation = false;
    }
    return addConfirmation;
}

bool clientInformation::removeFromFriendsList(clientInformation *nonFriend)
{
    bool removeConfirmation = false;
    if(nonFriend != NULL)
    {
	if(tableOfFriends.contains(nonFriend->getUserName())
	&& stringListOfFriends.contains(nonFriend->getUserName()))
	{
	    tableOfFriends.remove(nonFriend->getUserName());
	    stringListOfFriends.removeAll(nonFriend->getUserName());
	    removeConfirmation = true;
	}
	else
	{
	    removeConfirmation = false;
	}
    }
    else
    {
	removeConfirmation = false;
    }
    return removeConfirmation;
}

bool clientInformation::sendMessage(QString personThatSentMessage, QString message, QString timeSentAt)
{
    if(stringListOfFriends.contains(personThatSentMessage))
    {
	QByteArray dataBlock;
	QDataStream sendStream(&dataBlock, QIODevice::WriteOnly);
	sendStream.setVersion(QDataStream::Qt_4_7);

	// Users Protocol: <1> <Qstring username message sent from> <QString username message sent to> <QString message to send> <QString time message sent>
	sendStream << quint16(1) << (QString) personThatSentMessage << (QString) userName << (QString) message << (QString) timeSentAt;
	sock->write(dataBlock);
	sock->flush();
	sock->waitForBytesWritten();
	return true;
    }
    else
    {
	return false;
    }
}

// Only Setter for socket...the socket will change as users leave and
// log on again so socket has to be updated in order to talk to the user
void clientInformation::updateSocket(QTcpSocket *sockToUpdateTo)
{
    if(sockToUpdateTo != NULL)
    {
	sock = sockToUpdateTo;
    }
}

void clientInformation::sendOnlineFriendsList(QList<QString> serverUsersOnline)
{
    QStringList updatedListOfUsersOnline;

    // iterate over the current list of users online sent by the server
    foreach (QString user, stringListOfFriends)
    {
	// add only the users that are online and are friends of this user
	if(serverUsersOnline.contains(user))
	{
	    updatedListOfUsersOnline.push_front(user);
	}
    }

    QByteArray dataBlock;
    QDataStream sendStream(&dataBlock, QIODevice::WriteOnly);
    sendStream.setVersion(QDataStream::Qt_4_7);

    // Users Protocol: <2> <QStringList of updatedListOfUsersOnline>
    sendStream << quint16(2) << updatedListOfUsersOnline;
    sock->write(dataBlock);
    sock->flush();
    sock->waitForBytesWritten();
}

bool clientInformation::isUserFriend(QString user)
{
    if(!stringListOfFriends.isEmpty())
    {
	if(stringListOfFriends.contains(user))
	{
	    return true;
	}
	else
	{
	    return false;
	}
    }
    else
    {
	return false;
    }
}

void clientInformation::handleRemoveFriend(clientInformation *personSendingRequest, bool isValid)
{
    // if this user is a friend of ther person sending request, then only we can remove the friend
    // other wise we send back an invalid request packet to the person sending request
    if(isValid)
    {
	if(this->tableOfFriends.contains(personSendingRequest->getUserName())
	&& personSendingRequest->tableOfFriends.contains(this->getUserName()))
	{
	    this->removeFromFriendsList(personSendingRequest);
	    personSendingRequest->removeFromFriendsList(this);
	}
	else
	{
	    personSendingRequest->handleIsValidRemoveFriend(this->getUserName(), false);
	}
    }
    else
    {
	personSendingRequest->handleIsValidRemoveFriend(this->getUserName(), false);
    }
}

void clientInformation::handleIsValidRemoveFriend(QString personToRemove, bool isValid)
{
    QByteArray dataBlock;
    QDataStream sendStream(&dataBlock, QIODevice::WriteOnly);
    sendStream.setVersion(QDataStream::Qt_4_7);

    // Msg Protocol : <9> <QString friendUsername to be removed as a friend> <<bool> whether friend exists in server>
    sendStream << quint16(9) << (QString) personToRemove << isValid;
    sock->write(dataBlock);
    sock->flush();
    sock->waitForBytesWritten();
}

void clientInformation::handleAddFriend(QString personSendingRequest)
{
    QByteArray dataBlock;
    QDataStream sendStream(&dataBlock, QIODevice::WriteOnly);
    sendStream.setVersion(QDataStream::Qt_4_7);

    // Users Protocol: <6> <Qstring personSendingRequest>
    sendStream << quint16(6) << (QString) personSendingRequest;
    sock->write(dataBlock);
    sock->flush();
    sock->waitForBytesWritten();
}

void clientInformation::handleIsValidFriendRequest(QString personToAdd, bool isValid)
{
    QByteArray dataBlock;
    QDataStream sendStream(&dataBlock, QIODevice::WriteOnly);
    sendStream.setVersion(QDataStream::Qt_4_7);

    // Msg Protocol : <5> <QString friendUsername to be added as a friend> <<bool> whether friend exists in server>
    sendStream << quint16(5) << (QString) personToAdd << isValid;
    sock->write(dataBlock);
    sock->flush();
    sock->waitForBytesWritten();
}

void clientInformation::handleFriendAcceptance(clientInformation *sentUser, bool isAccepted)
{
    if(isAccepted)
    {
	this->addToFriendsList(sentUser);
	sentUser->addToFriendsList(this);
    }
}

void clientInformation::handleSendMessage(QString fromUser, QString toUser, QString message, QString timeSent)
{
    this->sendMessage(fromUser, message, timeSent);
}
